package controller

import (
	"fabric-explorer/entity"
	"fabric-explorer/service"
	"fabric-explorer/tools"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"
)

//查询账本基本信息
//区块高度、哈希等信息
func GetLedgerInfo(c *gin.Context) {
	info := entity.Info{}
	info.BlockHeight = service.GetBlockNum(bson.D{})
	info.TransactionNum = service.GetTransactionNum(bson.D{})
	//当日交易统计
	t := time.Now()
	info.CurrentTimestamp = t.UnixMilli()
	today := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
	todayTimestamp := today.UnixMilli()
	selecter := bson.D{{Key: "timestamp", Value: bson.D{{Key: "$gt", Value: todayTimestamp}}}}
	info.TransactionTodayNum = service.GetTransactionNum(selecter)
	if info.BlockHeight >= 1 {
		info.Timestamp = service.FindBlockOne(bson.D{{Key: "num", Value: 0}}).Timestamp
	}
	info.NodeList = service.GetAllNode()
	info.ChannelName = tools.ChannelID
	//event
	findoptions := &options.FindOptions{}
	pageSize := 7
	current := 1
	if pageSize > 0 {
		findoptions.SetLimit(int64(pageSize))
		findoptions.SetSkip(int64(pageSize * (current - 1)))
	}
	findoptions.SetSort(bson.M{"_id": -1})
	eventList := service.FindEventListPage(bson.D{}, findoptions)
	info.EventList = eventList
	info.NodeNum = int(service.GetNodeNum(bson.D{}))
	tools.SuccessResult(c, info)
}

//获得所有区块信息
func GetAllBlock(c *gin.Context) {
	tools.SuccessResult(c, service.GetAllBlock())
}

//分页查询区块信息
//入参 current,pageSize,num,channelId,blockHash
func GetAllBlockPage(c *gin.Context) {
	//request参数
	currentString := c.DefaultQuery("current", "1")
	pageSizeString := c.DefaultQuery("pageSize", "10")
	num := c.Query("num")
	channelId := c.Query("channelId")
	blockHash := c.Query("blockHash")
	current, err := strconv.Atoi(currentString)
	if err != nil {
		tools.FailResult(c, "current参数错误")
		return
	}
	pageSize, err := strconv.Atoi(pageSizeString)
	if err != nil {
		tools.FailResult(c, "pageSize参数错误")
		return
	}
	//根据参数查询,过滤
	selecter := bson.D{}
	//num
	if num != "" {
		numInt, err := strconv.Atoi(num)
		if err == nil {
			selecter = append(selecter, primitive.E{Key: "num", Value: numInt})
		}
	}
	//channelId
	if channelId != "" {
		selecter = append(selecter, bson.E{
			Key:   "channelId",
			Value: bson.M{"$regex": primitive.Regex{Pattern: ".*" + channelId + ".*", Options: "i"}},
		})
	}
	//blockHash
	if blockHash != "" {
		selecter = append(selecter, bson.E{
			Key:   "blockHash",
			Value: bson.M{"$regex": primitive.Regex{Pattern: ".*" + blockHash + ".*", Options: "i"}},
		})
		//selecter = append(selecter, primitive.E{Key: "blockHash", Value: blockHash})
	}
	//分页
	findoptions := &options.FindOptions{}
	if pageSize > 0 {
		findoptions.SetLimit(int64(pageSize))
		findoptions.SetSkip(int64(pageSize * (current - 1)))
	}
	findoptions.SetSort(bson.M{"_id": -1})
	resultData := service.FindBlockListPage(selecter, findoptions)
	tools.SuccessPageResult(c, resultData, current, pageSize, service.GetBlockNum(selecter))
}

//获得所有交易信息
func GetAllTransaction(c *gin.Context) {
	tools.SuccessResult(c, service.GetAllTransaction())
}

//获得一个交易信息
func GetTransactionById(c *gin.Context) {
	id := c.Query("id")
	if id == "" {
		tools.FailResult(c, "id required")
		return
	}
	tools.SuccessResult(c, service.FindTransactionOne(bson.D{{Key: "TxId", Value: id}}))
}

//获得所有交易信息分页
func GetAllTransactionPage(c *gin.Context) {
	//request参数
	currentString := c.DefaultQuery("current", "1")
	pageSizeString := c.DefaultQuery("pageSize", "10")
	TxId := c.Query("TxId")
	blockNum := c.Query("blockNum")
	chaincode := c.Query("chaincode")
	current, err := strconv.Atoi(currentString)
	if err != nil {
		tools.FailResult(c, "current参数错误")
		return
	}
	pageSize, err := strconv.Atoi(pageSizeString)
	if err != nil {
		tools.FailResult(c, "pageSize参数错误")
		return
	}
	selecter := bson.D{}
	//TxId
	if TxId != "" {
		//selecter = append(selecter, primitive.E{Key: "TxId", Value: TxId})
		selecter = append(selecter, bson.E{
			Key:   "TxId",
			Value: bson.M{"$regex": primitive.Regex{Pattern: ".*" + TxId + ".*", Options: "i"}},
		})
	}
	//blockNum
	if blockNum != "" {
		numInt, err := strconv.Atoi(blockNum)
		if err == nil {
			selecter = append(selecter, primitive.E{Key: "blockNum", Value: numInt})
		}
	}
	//chaincode
	if chaincode != "" {
		selecter = append(selecter, primitive.E{Key: "chaincode", Value: chaincode})
	}
	//分页
	findoptions := &options.FindOptions{}
	if pageSize > 0 {
		findoptions.SetLimit(int64(pageSize))
		findoptions.SetSkip(int64(pageSize * (current - 1)))
	}
	findoptions.SetSort(bson.M{"_id": -1})
	resultData := service.FindTransactionListPage(selecter, findoptions)
	tools.SuccessPageResult(c, resultData, current, pageSize, service.GetTransactionNum(selecter))
}

//获得所有节点
func GetAllNode(c *gin.Context) {
	tools.SuccessResult(c, service.GetAllNode())
}

//获得所有节点分页
func GetAllNodePage(c *gin.Context) {
	//request参数
	currentString := c.DefaultQuery("current", "1")
	pageSizeString := c.DefaultQuery("pageSize", "10")
	MSPID := c.Query("MSPID")
	name := c.Query("name")
	nodeType := c.Query("nodeType")
	current, err := strconv.Atoi(currentString)
	if err != nil {
		tools.FailResult(c, "current参数错误")
		return
	}
	pageSize, err := strconv.Atoi(pageSizeString)
	if err != nil {
		tools.FailResult(c, "pageSize参数错误")
		return
	}
	selecter := bson.D{}
	//MSPID
	if MSPID != "" {
		selecter = append(selecter, bson.E{
			Key:   "MSPID",
			Value: bson.M{"$regex": primitive.Regex{Pattern: ".*" + MSPID + ".*", Options: "i"}},
		})
	}
	//name
	if name != "" {
		selecter = append(selecter, bson.E{
			Key:   "name",
			Value: bson.M{"$regex": primitive.Regex{Pattern: ".*" + name + ".*", Options: "i"}},
		})
	}
	//nodeType
	if nodeType != "" {
		selecter = append(selecter, bson.E{Key: "nodeType", Value: nodeType})
	}
	//分页
	findoptions := &options.FindOptions{}
	if pageSize > 0 {
		findoptions.SetLimit(int64(pageSize))
		findoptions.SetSkip(int64(pageSize * (current - 1)))
	}
	resultData := service.FindNodeListPage(selecter, findoptions)
	tools.SuccessPageResult(c, resultData, current, pageSize, service.GetNodeNum(selecter))
}

//获得区块图表数据
func GetBlockChartData(c *gin.Context) {
	//取30天内的数据
	selecter := bson.D{}
	timeStart := time.Now().Add(-time.Hour * 24 * 30)
	selecter = append(selecter, bson.E{
		Key:   "timestamp",
		Value: bson.M{"$gte": timeStart.UnixMilli()},
	})
	blockList := service.FindBlockList(selecter)
	//key是日期，value是当天的区块数
	mapData := make(map[string]int, 0)
	for i := 0; i < len(blockList); i++ {
		block := blockList[i]
		timestamp := block.Timestamp
		t := time.UnixMilli(timestamp)
		date := t.Format("2006-01-02")
		n := mapData[date]
		mapData[date] = n + 1
	}

	tools.SuccessResult(c, lastFewsDaysChartData(mapData))
}

//获得区块图表数据
func GetBlockChartDataV2(c *gin.Context) {
	//取30天内的数据
	timeStart := time.Now().Add(-time.Hour * 24 * 29)
	currentYear := timeStart.Year()
	currentMonth := timeStart.Month()
	currentDay := timeStart.Day()
	timeStart = time.Date(currentYear, currentMonth, currentDay, 0, 0, 0, 0, time.Local)

	chartDataList := make([]entity.ChartData, 0)
	for i := 0; i < 30; i++ {
		date := timeStart.Format("2006-01-02")
		selecter := bson.D{}
		selecter = append(selecter, bson.E{
			Key:   "timestamp",
			Value: bson.M{"$gte": timeStart.UnixMilli()},
		})
		timeStart = timeStart.Add(time.Hour * 24)
		selecter = append(selecter, bson.E{
			Key:   "timestamp",
			Value: bson.M{"$lt": timeStart.UnixMilli()},
		})
		num := service.GetBlockNum(selecter)
		chartData := entity.ChartData{
			Date: date,
			Num:  int(num),
		}
		chartDataList = append(chartDataList, chartData)
	}
	tools.SuccessResult(c, chartDataList)
}

//获得交易图表数据
func GetTransactionChartData(c *gin.Context) {
	//取30天内的数据
	selecter := bson.D{}
	timeStart := time.Now().Add(-time.Hour * 24 * 30)
	selecter = append(selecter, bson.E{
		Key:   "timestamp",
		Value: bson.M{"$gte": timeStart.UnixMilli()},
	})
	transactionList := service.FindTransactionList(selecter)
	//key是日期，value是当天的区块数
	mapData := make(map[string]int, 0)
	for i := 0; i < len(transactionList); i++ {
		transaction := transactionList[i]
		timestamp := transaction.Timestamp
		t := time.UnixMilli(timestamp)
		date := t.Format("2006-01-02")
		n := mapData[date]
		mapData[date] = n + 1
	}
	tools.SuccessResult(c, lastFewsDaysChartData(mapData))
}

//获得交易图表数据
func GetTransactionChartDataV2(c *gin.Context) {
	//取30天内的数据
	timeStart := time.Now().Add(-time.Hour * 24 * 29)
	currentYear := timeStart.Year()
	currentMonth := timeStart.Month()
	currentDay := timeStart.Day()
	timeStart = time.Date(currentYear, currentMonth, currentDay, 0, 0, 0, 0, time.Local)

	chartDataList := make([]entity.ChartData, 0)
	for i := 0; i < 30; i++ {
		date := timeStart.Format("2006-01-02")
		selecter := bson.D{}
		selecter = append(selecter, bson.E{
			Key:   "timestamp",
			Value: bson.M{"$gte": timeStart.UnixMilli()},
		})
		timeStart = timeStart.Add(time.Hour * 24)
		selecter = append(selecter, bson.E{
			Key:   "timestamp",
			Value: bson.M{"$lt": timeStart.UnixMilli()},
		})
		num := service.GetTransactionNum(selecter)
		chartData := entity.ChartData{
			Date: date,
			Num:  int(num),
		}
		chartDataList = append(chartDataList, chartData)
	}
	tools.SuccessResult(c, chartDataList)
}

//获得所有交易信息
func GetAllEvent(c *gin.Context) {
	tools.SuccessResult(c, service.GetAllEvent())
}

//获得所有交易信息page
func GetAllEvenetPage(c *gin.Context) {
	//request参数
	currentString := c.DefaultQuery("current", "1")
	pageSizeString := c.DefaultQuery("pageSize", "10")
	t := c.Query("type")
	blockNum := c.Query("blockNum")
	chaincode := c.Query("chaincode")
	current, err := strconv.Atoi(currentString)
	if err != nil {
		tools.FailResult(c, "current参数错误")
		return
	}
	pageSize, err := strconv.Atoi(pageSizeString)
	if err != nil {
		tools.FailResult(c, "pageSize参数错误")
		return
	}
	selecter := bson.D{}
	//type
	if t != "" {
		selecter = append(selecter, bson.E{Key: "type", Value: t})
	}
	//blockNum
	if blockNum != "" {
		blockNumInt, err := strconv.Atoi(blockNum)
		if err == nil {
			selecter = append(selecter, bson.E{Key: "blockNum", Value: blockNumInt})
		}

	}
	//chaincode
	if chaincode != "" {
		selecter = append(selecter, bson.E{Key: "chaincode", Value: chaincode})
	}
	//分页
	findoptions := &options.FindOptions{}
	if pageSize > 0 {
		findoptions.SetLimit(int64(pageSize))
		findoptions.SetSkip(int64(pageSize * (current - 1)))
	}
	findoptions.SetSort(bson.M{"_id": -1})
	resultData := service.FindEventListPage(selecter, findoptions)
	tools.SuccessPageResult(c, resultData, current, pageSize, service.GetEventkNum(selecter))
}

//获得链码数据
func GetAllChaincode(c *gin.Context) {
	if service.GetChaincodekNum(bson.D{}) == 0 {
		service.InitChaincode()
	}
	tools.SuccessResult(c, service.GetAllChaincode())
}

//统计过去30天的表格数据
func lastFewsDaysChartData(mapData map[string]int) []entity.ChartData {
	chartDataList := make([]entity.ChartData, 0)
	//过去30天的数据
	timeStart := time.Now().Add(-time.Hour * 24 * 30)
	for i := 0; i < 30; i++ {
		timeStart = timeStart.Add(time.Hour * 24)
		date := timeStart.Format("2006-01-02")
		chartData := entity.ChartData{
			Date: date,
			Num:  mapData[date],
		}
		chartDataList = append(chartDataList, chartData)
	}
	return chartDataList
}
